/*
 *      visual.c
 *      
 *      Copyright 2009 Daniele Ricci <denn86@gmail.com>, Luca Saccagi <luksak86@gmail.com>
 *      
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *      
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *      
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 */
/**\file Questo file contiene tutte le funzioni di visualizzazione e di invio tramite rete dei risultati delle
 * operazioni richieste dalla query.
 */
#ifndef _VISUAL_IMPL
#define _VISUAL_IMPL

#include "visual.h"


/**\brief Costruzione del dato da inviare in rete
 *
 * Questa funzione si occupa di costruire, a partire dal risultato della query XPath, il messaggio da inviare in rete
 * \param nodes Insieme dei nodi che hanno dato esito positivo all'ezsecuzione della query XPath
 * \param xpath Parcorso XPath del campo da inviare
 * \param cn Connessione sulla quale inviare i dati
 * \param cn Canale sul quale inviare i dati
 * \param msg Contenuto del campo da inviare
 */
#ifdef _WIN32 
static char *print_xpath_nodes(xmlNodeSetPtr nodes,char *xpath,VortexConnection *cn,VortexChannel *ch,char *msg) {
#else
char *print_xpath_nodes(xmlNodeSetPtr nodes,char *xpath,VortexConnection *cn,VortexChannel *ch,char *msg) {
#endif
    int size,i;
	char tmp[2048];
    
    size = (nodes) ? nodes->nodeNr : 0;
    for(i=0;i<size;i++){
    	sprintf(tmp,"<item name=\"%s\">%s</item>",xpath,(char *)nodes->nodeTab[i]->children->content);
    	msg=(char *)realloc(msg,strlen(tmp)+strlen(msg)+1);
    	strncat(msg,tmp,strlen(tmp));    	
    }
    return msg;
}
/**\brief Funzione di visualizzazione o invio in rete del messaggio IDMEF
 *
 * Questa funzione gestisce la visualizzazione o l'invio in rete dei risultati dell'esecuzione delle query.
 * \param root Puntatore al nodo XML contenente l'alert da inviare
 * \param sel Lista di campi specificati nella sezione \aselect della query
 * \param cn Connessione sulla quale inviare i dati
 * \param cn Canale sul quale inviare i dati
 * \return bool True in caso di successo, False in caso di errore
 * In base al contenuto dei campi specificati nella sezione \aselect si procede in due modi:<br>
 * - Campi specificati come percorso XPath comportano la ricerca dei campi stessi e l'invio dei risultati in rete<br>
 * - Campi specificati in modo testuale comportano la visualizzazione in formato \ahuman \areadable dei dati
 */
#ifdef _WIN32 
static bool visualMessage(int sign_num,int step_num,AlertList *root,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#else
bool visualMessage(int sign_num,int step_num,AlertList *root,stringList *sel,VortexConnection *cn,VortexChannel *ch){
#endif
	xmlXPathContextPtr xpathCtx; 
    xmlXPathObjectPtr xpathObj;
    xmlNode *son;
	char *string;
	stringList *cur_sel;
	char *msg;

	root->match[sign_num]|=pow2[step_num];
	msg=(char *)malloc(sizeof(char));
	msg[0]='\0';
    for(cur_sel=sel;cur_sel;cur_sel=cur_sel->next){
		if(cur_sel->str[0]=='/' && cur_sel->str[1]!='e'){
			xmlUnlinkNode(xmlDocSetRootElement(doc, root->root));
			xpathCtx = xmlXPathNewContext(doc);
			if(xpathCtx == NULL) {
				fprintf(stderr,"ERR - unable to create new XPath context\n");
				return false;
			}	
			xpathObj = xmlXPathEvalExpression((xmlChar *)cur_sel->str, xpathCtx);

			if(xpathObj == NULL) {
				fprintf(stderr,"ERR - unable to evaluate xpath expression \n");
				return false;
			}
			msg=print_xpath_nodes(xpathObj->nodesetval,cur_sel->str,cn,ch,msg);
			doc->children=NULL; doc->parent=NULL; doc->next=NULL; doc->prev=NULL; doc->last=NULL;
			xmlXPathFreeObject(xpathObj);
			xmlXPathFreeContext(xpathCtx); 
			
		}else if(cur_sel->str[0]=='/' && cur_sel->str[1]=='e'){
			/* /exists condition matched */
			if(exists_sended==1){ free(msg); return true; }
			exists_sended=1;
			msg=(char*)realloc(msg,sizeof(char)*30);
			strcpy(msg,"<item name=\"/exists\"> </item>\0");
		}else{	
			if(strncasecmp(cur_sel->str,"message",strlen(cur_sel->str))==0){
				string=(char *)calloc(sizeof(char),6);
				strncpy(string,"Alert\0",6);
			}else{
				string=(char *)calloc(sizeof(char),strlen(cur_sel->str));
				strncpy(string,cur_sel->str,strlen(cur_sel->str));
			}
			for(son = root->root->CHILDREN; son; son = son->NEXT){
				if((strncasecmp((char *)son->name,"Alert",5)==0)&&(son->children!=NULL)){
					visualAlert(son,strlen(string),string);
				}
			}
			free(string);	
			string=NULL;
		}		
	}
	sending++;
	vortex_channel_send_ans_rpy(ch,msg,strlen(msg),msg_no);
	free(msg);
	msg=NULL;
	return true;
}	

#ifdef _WIN32 
static void visualAlert(xmlNode *root,int length, char *selstr){
#else
void visualAlert(xmlNode *root,int length, char *selstr){
#endif
	xmlNode *son;
	int i;
	char *str[12];
	
	printProp(root);
	if(strncasecmp(selstr,"Alert",length)==0){
		str[0]=(char *)calloc(sizeof(char),9);
		str[1]=(char *)calloc(sizeof(char),11);
		str[2]=(char *)calloc(sizeof(char),11);
		str[3]=(char *)calloc(sizeof(char),13);
		str[4]=(char *)calloc(sizeof(char),7);
		str[5]=(char *)calloc(sizeof(char),7);
		str[6]=(char *)calloc(sizeof(char),15);
		str[7]=(char *)calloc(sizeof(char),11);
		str[8]=(char *)calloc(sizeof(char),10);
		str[9]=(char *)calloc(sizeof(char),14);
		str[10]=(char *)calloc(sizeof(char),17);
		str[11]=(char *)calloc(sizeof(char),15);
		strncpy(str[0],"Analyzer\0",9);
		strncpy(str[1],"CreateTime\0",11);
		strncpy(str[2],"DetectTime\0",11);
		strncpy(str[3],"AnalyzerTime\0",13);
		strncpy(str[4],"Source\0",7);
		strncpy(str[5],"Target\0",7);
		strncpy(str[6],"Classification\0",15);
		strncpy(str[7],"Assessment\0",11);
		strncpy(str[8],"Toolalert\0",10);
		strncpy(str[9],"OverflowAlert\0",14);
		strncpy(str[10],"CorrelationAlert\0",17);
		strncpy(str[11],"AdditionalData\0",15);
	}else{
		for(i=0;i<12;i++){
			str[i]=(char *)calloc(sizeof(char),length);
			strncpy(str[i],selstr,length);
		}
	}
	
	for(son = root->CHILDREN; son; son = son->NEXT){
		if((strncasecmp((char *)son->name,"Analyzer",8)==0)&&(son->children!=NULL)){
			visualAnalyzer(son,strlen(str[0]),str[0]);
		}
		if((strncasecmp((char *)son->name,"CreateTime",10)==0)&&(son->children!=NULL)){
			visualTime(son,strlen(str[1]),str[1]);
		}
		if((strncasecmp((char *)son->name,"DetectTime",10)==0)&&(son->children!=NULL)){
			visualTime(son,strlen(str[2]),str[2]);
		}
		if((strncasecmp((char *)son->name,"AnalyzerTime",12)==0)&&(son->children!=NULL)){
			visualTime(son,strlen(str[3]),str[3]);
		}
		if((strncasecmp((char *)son->name,"Source",6)==0)&&(son->children!=NULL)){
			visualSource(son,strlen(str[4]),str[4]);
		}
		if((strncasecmp((char *)son->name,"Target",6)==0)&&(son->children!=NULL)){
			visualTarget(son,strlen(str[5]),str[5]);
		}
		if((strncasecmp((char *)son->name,"Classification",14)==0)&&(son->children!=NULL)){
			visualClassification(son,strlen(str[6]),str[6]);
		}
		if((strncasecmp((char *)son->name,"Assessment",10)==0)&&(son->children!=NULL)){
			visualAssessment(son,strlen(str[7]),str[7]);
		}
		if((strncasecmp((char *)son->name,"ToolAlert",9)==0)&&(son->children!=NULL)){
			visualToolAlert(son,strlen(str[8]),str[8]);
		}
		if((strncasecmp((char *)son->name,"OverflowAlert",13)==0)&&(son->children!=NULL)){
			visualOvrfAlert(son,strlen(str[9]),str[9]);
		}
		if((strncasecmp((char *)son->name,"CorrelationAlert",16)==0)&&(son->children!=NULL)){
			visualCorrAlert(son,strlen(str[10]),str[10]);
		}
		if((strncasecmp((char *)son->name,"AdditionalData",14)==0)&&(son->children!=NULL)){
			printSubTree(son,strlen(str[11]),str[11],"AdditionalData");
		}
	}
	for(i=0;i<12;i++){ free(str[i]); str[i]=NULL;}
}

#ifdef _WIN32 
static void visualAnalyzer(xmlNode *root,int length, char *selstr){
#else
void visualAnalyzer(xmlNode *root,int length, char *selstr){
#endif
	xmlNode *son;
	int i;
	char *str[3];
	
	if(strncasecmp(selstr,"Analyzer",length)==0){
		printProp(root);
		str[0]=(char *)malloc(sizeof(char)*5);
		str[1]=(char *)malloc(sizeof(char)*8);
		str[2]=(char *)malloc(sizeof(char)*9);
		strncpy(str[0],"Node\0",5);
		strncpy(str[1],"Process\0",8);
		strncpy(str[2],"Analyzer\0",9);
	}else{
		for(i=0;i<3;i++){
			str[i]=(char *)calloc(sizeof(char),length);
			strncpy(str[i],selstr,length);
		}
	}
	
	for(son = root->CHILDREN; son; son = son->NEXT){
		if((strncasecmp((char *)son->name,"Node",4)==0)&&(son->children!=NULL)){
			visualNode(son,strlen(str[0]),str[0]);
		}
		if((strncasecmp((char *)son->name,"Process",7)==0)&&(son->children!=NULL)){
			printSubTree(son,strlen(str[1]),str[1],"Process");
		}
		if((strncasecmp((char *)son->name,"Analyzer",8)==0)&&(son->children!=NULL)){
			visualAnalyzer(son,strlen(str[2]),str[2]);
		}
	}
	for(i=0;i<3;i++){ free(str[i]); str[i]=NULL;}
}

#ifdef _WIN32 
static void visualNode(xmlNode *root,int length, char *selstr){
#else
void visualNode(xmlNode *root,int length, char *selstr){
#endif
	xmlNode *son;
	
	if(strncasecmp(selstr,"Node",length)==0){
		printProp(root);
	}
	for(son = root->CHILDREN; son; son = son->NEXT){
		if(((strncasecmp((char *)son->name,"location",8)==0) || (strncasecmp((char *)son->name,"name",4)==0)) &&(son->children!=NULL)){
			if(son->CONTENT!=NULL){
				if(strncasecmp(selstr,"Node",length)==0){
					printf("\t%s: %s\n", strtoupr((char *)son->name),son->CONTENT);
				}
			}
		}
		if((strncasecmp((char *)son->name,"Address",7)==0)&&(son->children!=NULL)){
			if(strncasecmp(selstr,"Node",length)==0){
				printSubTree(son,7,"Address","Address");
			}else{
				printSubTree(son,length,selstr,"Address");
			}
		}
	}
}

#ifdef _WIN32 
static void visualTime(xmlNode *root,int length, char *selstr){
#else
void visualTime(xmlNode *root,int length, char *selstr){
#endif
	xmlNode *son;
	
	if((strncasecmp(selstr,"CreateTime",length)==0) || (strncasecmp(selstr,"DetectTime",length)==0) || (strncasecmp(selstr,"AnalyzerTime",length)==0)){
		printProp(root);
		/////////////////////////////////////////////////////////////
		for(son = root->CHILDREN; son; son = son->NEXT){
			if(son->content!=NULL){
				printf("\tTIME: %s\n",son->content);
			}
		}
	}
}

#ifdef _WIN32 
static void visualSource(xmlNode *root,int length, char *selstr){
#else
void visualSource(xmlNode *root,int length, char *selstr){
#endif
	xmlNode *son;
	int i;
	char *str[4];
	
	if(strncasecmp(selstr,"Source",length)==0){
		printProp(root);
		str[0]=(char *)calloc(sizeof(char),5);
		str[1]=(char *)calloc(sizeof(char),5);
		str[2]=(char *)calloc(sizeof(char),8);
		str[3]=(char *)calloc(sizeof(char),8);
		strncpy(str[0],"Node\0",5);
		strncpy(str[1],"User\0",5);
		strncpy(str[2],"Process\0",8);
		strncpy(str[3],"Service\0",8);
	}else{
		for(i=0;i<4;i++){
			str[i]=(char *)calloc(sizeof(char),length);
			strncpy(str[i],selstr,length);
		}
	}
	
	for(son = root->CHILDREN; son; son = son->NEXT){
		if((strncasecmp((char *)son->name,"Node",5)==0)&&(son->children!=NULL)){
			visualNode(son,strlen(str[0]),str[0]);
		}
		if((strncasecmp((char *)son->name,"User",5)==0)&&(son->children!=NULL)){
			visualUser(son,strlen(str[1]),str[1]);
		}
		if((strncasecmp((char *)son->name,"Process",8)==0)&&(son->children!=NULL)){
			printSubTree(son,strlen(str[2]),str[2],"Process");
		}
		if((strncasecmp((char *)son->name,"Service",8)==0)&&(son->children!=NULL)){
			printSubTree(son,strlen(str[3]),str[3],"Service");
		}
	}
	for(i=0;i<4;i++){ free(str[i]); str[i]=NULL;}
}

#ifdef _WIN32 
static void visualUser(xmlNode *root,int length, char *selstr){
#else
void visualUser(xmlNode *root,int length, char *selstr){
#endif
	xmlNode *son;
	char *str;
	
	if(strncasecmp(selstr,"Source",length)==0){
		printProp(root);
		str=(char *)calloc(sizeof(char),8);
		strncpy(str,"UserId\0",8);
	}else{
		str=(char *)calloc(sizeof(char),length);
		strncpy(str,selstr,length);
	}
	for(son = root->CHILDREN; son; son = son->NEXT){
		if((strncasecmp((char *)son->name,"UserId",7)==0)&&(son->children!=NULL)){
			printSubTree(son,strlen(str),str,"UserId");
		}
	}
	free(str);
	str=NULL;
}

#ifdef _WIN32 
static void visualTarget(xmlNode *root,int length, char *selstr){
#else
void visualTarget(xmlNode *root,int length, char *selstr){
#endif
	xmlNode *son;
	int i;
	char *str[5];
	
	if(strncasecmp(selstr,"Target",length)==0){
		printProp(root);
		str[0]=(char *)calloc(sizeof(char),5);
		str[1]=(char *)calloc(sizeof(char),5);
		str[2]=(char *)calloc(sizeof(char),8);
		str[3]=(char *)calloc(sizeof(char),8);
		str[4]=(char *)calloc(sizeof(char),5);
		strncpy(str[0],"Node\0",5);
		strncpy(str[1],"User\0",5);
		strncpy(str[2],"Process\0",8);
		strncpy(str[3],"Service\0",8);
		strncpy(str[4],"File\0",5);
	}else{
		for(i=0;i<5;i++){
			str[i]=(char *)calloc(sizeof(char),length);
			strncpy(str[i],selstr,length);
		}
	}
	
	for(son = root->CHILDREN; son; son = son->NEXT){
		if((strncasecmp((char *)son->name,"Node",5)==0)&&(son->children!=NULL)){
			visualNode(son,strlen(str[0]),str[0]);
		}
		if((strncasecmp((char *)son->name,"User",5)==0)&&(son->children!=NULL)){
			visualUser(son,strlen(str[1]),str[1]);
		}
		if((strncasecmp((char *)son->name,"Process",8)==0)&&(son->children!=NULL)){
			printSubTree(son,strlen(str[2]),str[2],"Process");
		}
		if((strncasecmp((char *)son->name,"Service",8)==0)&&(son->children!=NULL)){
			printSubTree(son,strlen(str[3]),str[3],"Service");
		}
		if((strncasecmp((char *)son->name,"File",5)==0)&&(son->children!=NULL)){
			printSubTree(son,strlen(str[4]),str[4],"File");
		}
	}
	for(i=0;i<5;i++){ free(str[i]); str[i]=NULL;}
}

#ifdef _WIN32 
static void visualClassification(xmlNode *root,int length, char *selstr){
#else
void visualClassification(xmlNode *root,int length, char *selstr){
#endif
	xmlNode *son;
	
	if(strncasecmp(selstr,"Classification",length)==0){
		printProp(root);
		for(son = root->CHILDREN; son; son = son->NEXT){
			if((strncasecmp((char *)son->name,"Reference",10)==0)&&(son->children!=NULL)){
				printSubTree(son,strlen((char *)son->name),(char *)son->name,"Reference");
			}else{
				printf("%s\t",strtoupr((char *)son->name));
				printProp(son);
				if(son->CONTENT!=NULL)
					printf("\tCONTENT: %s\n",(char *)son->CONTENT);
			}
		}	
	}
}

#ifdef _WIN32 
static void visualAssessment(xmlNode *root,int length, char *selstr){
#else
void visualAssessment(xmlNode *root,int length, char *selstr){
#endif
	xmlNode *son;
	
	if(strncasecmp(selstr,"Assessment",length)==0){
		printf("%s\n",strtoupr((char *)root->name));
		for(son = root->CHILDREN; son; son = son->NEXT){
			printProp(son);
		}
	}
}

#ifdef _WIN32 
static void visualToolAlert(xmlNode *root,int length, char *selstr){
#else
void visualToolAlert(xmlNode *root,int length, char *selstr){
#endif
	xmlNode *son;
		
	if(strncasecmp(selstr,"Reference",length)==0){
		printf("%s\n",strtoupr((char *)root->name));
		for(son = root->CHILDREN; son; son = son->NEXT){
			if(strncasecmp((char *)son->name,"Alertident",10)!=0){
				if(son->CONTENT!=NULL){
					printf("%s: %s\n",strtoupr((char *)son->name),son->CONTENT);
				}
			}else{
				printf("%s: %s\n",strtoupr((char *)son->properties->name),son->properties->CONTENT);	
			}
		}
	}
}

#ifdef _WIN32 
static void visualOvrfAlert(xmlNode *root,int length, char *selstr){
#else
void visualOvrfAlert(xmlNode *root,int length, char *selstr){
#endif
	if(strncasecmp(selstr,"Reference",length)==0){
		printf("%s\n",strtoupr((char *)root->name));
		printSons(root);
	}
}

#ifdef _WIN32 
static void visualCorrAlert(xmlNode *root,int length, char *selstr){
#else
void visualCorrAlert(xmlNode *root,int length, char *selstr){
#endif
	xmlNode *son;
	
	if(strncasecmp(selstr,"Reference",length)==0){
		printf("%s\n",strtoupr((char *)root->name));
		for(son = root->CHILDREN; son; son = son->NEXT){
			if(strncasecmp((char *)son->name,"Alertident",10)!=0){
				if(son->CONTENT!=NULL){
					printf("%s: %s\n",strtoupr((char *)son->name),son->CONTENT);
				}
			}else{
				printf("%s: %s\n",strtoupr((char *)son->properties->name),son->properties->CONTENT);	
			}
		}
	}
}

#endif
